/*************************************************************************************
 *	模块名称 : TCP模块头文件
 *	文件名称 : mytcp.c
 *	版   本 : V1.0
 *	说   明 : 本文件包含了对 TCP服务器 和 TCP客户端 的常用操作的 封装函数的实现.
 *	修改记录 :
 *		     版本号       日期         作者        说明
 *	         V1.0     2022-06-19      YT        发布
 *
 *	Copyright (C), 2022-2030, Zhirui
 *************************************************************************************/
#include "mytcp.h"

static int gs_ListenSockFd;


int TcpServerInit( const char strServerIp[], int ServerPort )
{
    gs_ListenSockFd = socket( AF_INET, SOCK_STREAM, 0 );
    if ( -1 == gs_ListenSockFd )
    {
        perror( "fail socket @ TcpServerInit" );
        return -1;
    }

    int Ret;

    struct sockaddr_in ServerAddr;
    ServerAddr.sin_family      = AF_INET;
    ServerAddr.sin_port        = htons( ServerPort );
    ServerAddr.sin_addr.s_addr = inet_addr( strServerIp );
    Ret = bind( gs_ListenSockFd, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr) );
    if ( -1 == Ret )
    {
        perror( "fail socket @ TcpServerInit" );
        return -1;
    }

    Ret = listen( gs_ListenSockFd, LISTEN_NUM );
    if ( -1 == Ret )
    {
        perror( "fail listen @ TcpServerInit" );
        return -1;
    }

    return 0;
}

int TcpServerAccept( int *pConnectSockFd, char strClintIp[], int *pClintPort )
{
    int ConnectSockFd;
    struct sockaddr_in ClintAddr;
    socklen_t ClintAddrLen = sizeof(ClintAddr);

    ConnectSockFd = accept( gs_ListenSockFd, (struct sockaddr*)&ClintAddr, &ClintAddrLen );
    if ( -1 == ConnectSockFd ) 
    {
        perror( "fail accept" );
        return -1;
    }

    *pConnectSockFd = ConnectSockFd;

    if( strClintIp != NULL )
    {
        strcpy( strClintIp, inet_ntoa(ClintAddr.sin_addr) );
    }

    if( pClintPort != NULL )
    {
        *pClintPort = ntohs(ClintAddr.sin_port);
    }

    return 0;
}

int TcpServerClose( void )
{
    close( gs_ListenSockFd );
    return 0;
}

int TcpClintConnect( int *pConnectSockFd, const char strServerIp[], int ServerPort )
{
    int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
    if ( -1 == sockfd )
    {
        perror( "fail socket @ TcpClintConnect" );
        return -1;
    }
    *pConnectSockFd = sockfd;

    struct sockaddr_in siServer;
    siServer.sin_family = AF_INET;
    siServer.sin_port   = htons( ServerPort );
    siServer.sin_addr.s_addr = inet_addr( strServerIp );
    
    int iRet;
    iRet = connect( sockfd, (struct sockaddr *)&siServer, sizeof(siServer) );
    if ( -1 == iRet )
    {
        perror( "fail connect" );
        return -1;
    }

    return 0;
}